package com.xnyzc.lhy.order.service.impl.carpool;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xnyzc.lhy.common.component.redis.RedisCommon;
import com.xnyzc.lhy.common.constant.RedisPrefixConstant;
import com.xnyzc.lhy.common.exception.PangException;
import com.xnyzc.lhy.common.penum.EErrorCode;
import com.xnyzc.lhy.common.penum.EOrderType;
import com.xnyzc.lhy.common.penum.carpool.EInvitationType;
import com.xnyzc.lhy.common.penum.carpool.EIsRegistered;
import com.xnyzc.lhy.common.penum.client.EClientUserType;
import com.xnyzc.lhy.common.penum.order.EInvoiceStatus;
import com.xnyzc.lhy.common.penum.order.EOrderStatus;
import com.xnyzc.lhy.common.penum.tab.ETab;
import com.xnyzc.lhy.common.util.CheckUtil;
import com.xnyzc.lhy.order.entity.order.OaCOrder;
import com.xnyzc.lhy.order.entity.order.OaCOrderApprovalOfficial;
import com.xnyzc.lhy.order.entity.order.OaCOrderPersonal;
import com.xnyzc.lhy.order.entity.order.OaCOrderPersonalOfficial;
import com.xnyzc.lhy.order.entity.order.OaDOrder;
import com.xnyzc.lhy.order.entity.param.carpool.InviteCarpoolParam;
import com.xnyzc.lhy.order.entity.system.OaSysGlobalConfig;
import com.xnyzc.lhy.order.entity.user.OaCUser;
import com.xnyzc.lhy.order.entity.user.tab.OaTabUser;
import com.xnyzc.lhy.order.mapper.order.OaCOrderApprovalOfficialMapper;
import com.xnyzc.lhy.order.mapper.order.OaCOrderPersonalMapper;
import com.xnyzc.lhy.order.mapper.order.OaCOrderPersonalOfficialMapper;
import com.xnyzc.lhy.order.mapper.order.OaDOrderMapper;
import com.xnyzc.lhy.order.mapper.system.OaSysGlobalConfigMapper;
import com.xnyzc.lhy.order.mapper.user.OaCUserMapper;
import com.xnyzc.lhy.order.mapper.user.tab.OaTabUserMapper;
import com.xnyzc.lhy.order.service.carpool.InviteCarpoolService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description 邀约拼车
 * @Author zhuyubin
 * @Date 2019-09-25 15:03
 **/
@Slf4j
@Service
public class InviteCarpoolServiceImpl implements InviteCarpoolService {

    @Autowired
    private OaCUserMapper oaCUserMapper;
    @Autowired
    private OaSysGlobalConfigMapper oaSysGlobalConfigMapper;
    @Autowired
    private OaTabUserMapper oaTabUserMapper;
    @Autowired
    private OaCOrderPersonalOfficialMapper oaCOrderPersonalOfficialMapper;
    @Autowired
    private OaCOrderApprovalOfficialMapper oaCOrderApprovalOfficialMapper;
    @Autowired
    private OaCOrderPersonalMapper oaCOrderPersonalMapper;
    @Autowired
    private OaDOrderMapper oaDOrderMapper;
    @Autowired
    private RedisCommon redisCommon;

    /**
     * 修改订单
     * @param userId 乘客id
     * @param tag 用户来源
     * @param inviteCarpoolParam 修改参数
     * @return
     */
    @Override
    public String updateInviteCarpoolOrder(Long userId, String tag, InviteCarpoolParam inviteCarpoolParam){
        // 订单号
        String orderNo = inviteCarpoolParam.getOrderNo();
        if (CheckUtil.objIsEmpty(orderNo)){
            log.info(String.format("用户来源 %s,修改邀约订单订单号为空", tag));
            throw PangException.create(EErrorCode.missingArg);
        }
        // 乘车人姓名
        String inviteName = inviteCarpoolParam.getInviteName();
        // 乘车人姓名
        String invitePhone = inviteCarpoolParam.getInvitePhone();
        // 出发地地址、经度、纬度
        String startAddress = inviteCarpoolParam.getStartAddress();
        String startLng = inviteCarpoolParam.getStartLng();
        String startLat = inviteCarpoolParam.getStartLat();
        // 目的地地址、经度、纬度
        String endAddress = inviteCarpoolParam.getEndAddress();
        String endLng = inviteCarpoolParam.getEndLng();
        String endLat = inviteCarpoolParam.getEndLat();
        Integer invitationStatus;
        // 个人公务
        if (orderNo.contains(EOrderType.GRGW.getDesc())){
            // 修改乘客订单
            invitationStatus = this.updatePersonalOfficialOrder(userId, tag, orderNo, startAddress, startLng, startLat, invitePhone, inviteName, endAddress, endLng, endLat);
        }
        // 审批公务
        else if (orderNo.contains(EOrderType.SPGW.getDesc())){
            // 修改乘客订单
            invitationStatus = this.updateApprovalOfficialOrder(userId, tag, orderNo, startAddress, startLng, startLat, invitePhone, inviteName, endAddress, endLng, endLat);
        }
        // 自费叫车
        else if (orderNo.contains(EOrderType.ZFJC.getDesc())){
            // 修改乘客订单
            invitationStatus = this.updatePersonalOrder(userId, tag, orderNo, startAddress, startLng, startLat, invitePhone, inviteName, endAddress, endLng, endLat);
        }
        // 订单类型不是邀约订单
        else {
            log.info(String.format("用户来源 %s,订单号 %s,当前订单号不是个人公务或审批公务订单号", tag, orderNo));
            throw PangException.create(EErrorCode.notInviteCarpoolOrder);
        }
        if (CheckUtil.objIsNotEmpty(invitationStatus) && EInvoiceStatus.beInvitationPersonAgrees.getValue().equals(invitationStatus)){
            // 修改司机订单
            this.updateOaDOrder(tag, orderNo, startLng, startLat, invitePhone, inviteName, endLng, endLat);
        }
        return EErrorCode.updateInviteCarpoolOrderSuccess.getDesc();
    }

    /**
     * 根据手机号显示选项
     * 邀约拼车页面信息
     * @param invitePhone 被邀人手机号
     * @param tag 用户来源
     * @return
     */
    @Override
    public Map<String, Object> inviteCarpoolInfo(String invitePhone, String tag){
        Map<String, Object> result = this.initInviteCarpoolInfo();
        List<Map<String, Object>> invitationTypeList = new ArrayList<>();
        Map<String, Object> map = new HashMap<>(16);
        map.put("code", EInvitationType.personal.getValue());
        map.put("msg", EInvitationType.personal.getDesc());
        invitationTypeList.add(map);
        // 用户基础
        List<OaCUser> oaCUserList = oaCUserMapper.selectList(Wrappers.<OaCUser>lambdaQuery().eq(OaCUser::getTag, tag).eq(OaCUser::getUserPhone, invitePhone));
        // 全局配置
        List<OaSysGlobalConfig> oaSysGlobalConfigs = oaSysGlobalConfigMapper.selectList(Wrappers.<OaSysGlobalConfig>lambdaQuery().eq(OaSysGlobalConfig::getTag, tag));
        if (oaSysGlobalConfigs.size() != 1){
            log.info(String.format("用户来源 %s 在全局配置中未获取到数据", tag));
            throw PangException.create(EErrorCode.oaSysGlobalConfigIsNull);
        }
        OaSysGlobalConfig oaSysGlobalConfig = oaSysGlobalConfigs.get(0);
        // 注册了
        if (oaCUserList.size() == 1){
            result.put("isRegistered", EIsRegistered.yes.getValue());
            result.put("isRegisteredMsg", EIsRegistered.yes.getDesc());
            OaCUser oaCUser = oaCUserList.get(0);
            Integer integer = 0;
            List<OaTabUser> oaTabUsers = oaTabUserMapper.selectList(
                    Wrappers.<OaTabUser>lambdaQuery()
                            .eq(OaTabUser::getTag, tag)
                            .eq(OaTabUser::getUserId, oaCUser.getUserId())
                            .eq(OaTabUser::getUserType, EClientUserType.c.getValue()));
            for (OaTabUser oaTabUser : oaTabUsers) {
                Integer tabId = oaTabUser.getTabId();
                if (ETab.official.getValue().equals(tabId) || ETab.approval.getValue().equals(tabId)){
                    integer += 1;
                }
            }
            if (integer > 0){
                map = new HashMap<>(16);
                map.put("code", EInvitationType.office.getValue());
                map.put("msg", EInvitationType.office.getDesc());
                invitationTypeList.add(map);
            } else {
                String invitationRegisteredLabel = oaSysGlobalConfig.getInvitationRegisteredLabel();
                result.put("prompt", CheckUtil.strIsNotEmpty(invitationRegisteredLabel) ? invitationRegisteredLabel : "");
            }
        }
        // 未注册
        else if (oaCUserList.size() == 0){
            String invitationUnregisteredLabel = oaSysGlobalConfig.getInvitationUnregisteredLabel();
            result.put("isRegistered", EIsRegistered.no.getValue());
            result.put("isRegisteredMsg", EIsRegistered.no.getDesc());
            result.put("prompt", CheckUtil.strIsNotEmpty(invitationUnregisteredLabel) ? invitationUnregisteredLabel : "");
        } else {
            log.info(String.format("用户来源 %s 出现重复手机号 %s", tag, invitePhone));
            throw PangException.create(EErrorCode.repeatPhone);
        }
        result.put("invitationTypeList", invitationTypeList);
        return result;
    }

    /**
     * 初始化邀约拼车页面出参
     * @return
     */
    private Map<String, Object> initInviteCarpoolInfo(){
        Map<String, Object> result = new HashMap<>(16);
        result.put("isRegistered", EIsRegistered.no.getValue());
        result.put("isRegisteredMsg", EIsRegistered.no.getDesc());
        result.put("prompt", "");
        result.put("invitationTypeList", new ArrayList<>());
        return result;
    }

    /**
     * 修改司机订单
     * @param tag 用户来源
     * @param orderNo 订单号
     * @param startLng 出发地经度
     * @param startLat 出发地纬度
     * @param invitePhone 乘车人手机号
     * @param inviteName 乘车人姓名
     * @param endLng 目的地经度
     * @param endLat 目的地纬度
     */
    private void updateOaDOrder(String tag, String orderNo, String startLng, String startLat, String invitePhone, String inviteName, String endLng, String endLat){
        List<OaDOrder> oaDOrders = oaDOrderMapper.selectList(Wrappers.<OaDOrder>lambdaQuery().eq(OaDOrder::getTag, tag).eq(OaDOrder::getOrderNo, orderNo));
        if (oaDOrders.size() != 1) {
            log.info(String.format("用户来源 %s,订单号 %s,未查到正确数量的订单", tag, orderNo));
            throw PangException.create(EErrorCode.unInviteCarpoolOrder);
        }
        OaDOrder oaDOrder = oaDOrders.get(0);
        // 订单不为 3司机已接单4司机前往预约地点5司机到达6行程中13私用行程 才可修改出发地
        Integer orderStatus = oaDOrder.getOrderStatus();
        if (this.ifUpdateDeparture(orderStatus)){
            oaDOrder.setFlng(startLng);
            oaDOrder.setFlat(startLat);
        }
        oaDOrder.setPassengerPhone(invitePhone);
        oaDOrder.setPassengerName(inviteName);
        oaDOrder.setTlng(endLng);
        oaDOrder.setTlat(endLat);
        int i = oaDOrderMapper.updateById(oaDOrder);
        if (i != 1){
            throw PangException.create(EErrorCode.updateInviteCarpoolOrderFailure);
        }
        // 更新redis订单
        this.updateRedisOrderNo(orderNo, JSON.toJSONString(oaDOrder));
    }

    /**
     * 修改自费叫车订单
     * @param userId 乘客id
     * @param tag 用户来源
     * @param orderNo 订单号
     * @param startAddress 出发地
     * @param startLng 出发地经度
     * @param startLat 出发地纬度
     * @param invitePhone 乘车人手机号
     * @param inviteName 乘车人姓名
     * @param endAddress 目的地
     * @param endLng 目的地经度
     * @param endLat 目的地纬度
     */
    private Integer updatePersonalOrder(
            Long userId,
            String tag,
            String orderNo,
            String startAddress,
            String startLng,
            String startLat,
            String invitePhone,
            String inviteName,
            String endAddress,
            String endLng,
            String endLat){
        List<OaCOrderPersonal> oaCOrderPersonals = oaCOrderPersonalMapper.selectList(
                Wrappers.<OaCOrderPersonal>lambdaQuery()
                        .eq(OaCOrder::getTag, tag)
                        .eq(OaCOrder::getOrderNo, orderNo)
                        .eq(OaCOrder::getUserId, userId));
        if (oaCOrderPersonals.size() != 1) {
            log.info(String.format("用户来源 %s,订单号 %s,未查到正确数量的乘客订单", tag, orderNo));
            throw PangException.create(EErrorCode.unInviteCarpoolOrder);
        }
        OaCOrderPersonal oaCOrderPersonal = oaCOrderPersonals.get(0);
        oaCOrderPersonal.setPassengerPhone(invitePhone);
        oaCOrderPersonal.setPassengerName(inviteName);
        oaCOrderPersonal.setEndAddress(endAddress);
        oaCOrderPersonal.setEndLng(endLng);
        oaCOrderPersonal.setEndLat(endLat);
        // 订单不为 3司机已接单4司机前往预约地点5司机到达6行程中13私用行程 才可修改出发地
        Integer orderStatus = oaCOrderPersonal.getOrderStatus();
        if (this.ifUpdateDeparture(orderStatus)){
            oaCOrderPersonal.setStartAddress(startAddress);
            oaCOrderPersonal.setStartLng(startLng);
            oaCOrderPersonal.setStartLat(startLat);
        }
        int i = oaCOrderPersonalMapper.updateById(oaCOrderPersonal);
        if (i != 1){
            throw PangException.create(EErrorCode.updateInviteCarpoolOrderFailure);
        }
        // 更新redis订单
        this.updateRedisOrderNo(orderNo, JSON.toJSONString(oaCOrderPersonal));
        return oaCOrderPersonal.getInvitationStatus();
    }

    /**
     * 修改个人公务订单
     * @param userId 乘客id
     * @param tag 用户来源
     * @param orderNo 订单号
     * @param startAddress 出发地
     * @param startLng 出发地经度
     * @param startLat 出发地纬度
     * @param invitePhone 乘车人手机号
     * @param inviteName 乘车人姓名
     * @param endAddress 目的地
     * @param endLng 目的地经度
     * @param endLat 目的地纬度
     */
    private Integer updatePersonalOfficialOrder(
            Long userId,
            String tag,
            String orderNo,
            String startAddress,
            String startLng,
            String startLat,
            String invitePhone,
            String inviteName,
            String endAddress,
            String endLng,
            String endLat){
        List<OaCOrderPersonalOfficial> personalOfficials = oaCOrderPersonalOfficialMapper.selectList(
                Wrappers.<OaCOrderPersonalOfficial>lambdaQuery()
                        .eq(OaCOrder::getTag, tag)
                        .eq(OaCOrder::getOrderNo, orderNo)
                        .eq(OaCOrder::getUserId, userId));
        if (personalOfficials.size() != 1) {
            log.info(String.format("用户来源 %s,订单号 %s,未查到正确数量的乘客订单", tag, orderNo));
            throw PangException.create(EErrorCode.unInviteCarpoolOrder);
        }
        OaCOrderPersonalOfficial personalOfficial = personalOfficials.get(0);
        // 订单不为 3司机已接单4司机前往预约地点5司机到达6行程中13私用行程 才可修改出发地
        Integer orderStatus = personalOfficial.getOrderStatus();
        if (this.ifUpdateDeparture(orderStatus)){
            personalOfficial.setStartAddress(startAddress);
            personalOfficial.setStartLng(startLng);
            personalOfficial.setStartLat(startLat);
        }
        personalOfficial.setPassengerPhone(invitePhone);
        personalOfficial.setPassengerName(inviteName);
        personalOfficial.setEndAddress(endAddress);
        personalOfficial.setEndLng(endLng);
        personalOfficial.setEndLat(endLat);
        int i = oaCOrderPersonalOfficialMapper.updateById(personalOfficial);
        if (i != 1){
            throw PangException.create(EErrorCode.updateInviteCarpoolOrderFailure);
        }
        // 更新redis订单
        this.updateRedisOrderNo(orderNo, JSON.toJSONString(personalOfficial));
        return personalOfficial.getInvitationStatus();
    }

    /**
     * 修改审批订单
     * @param userId 乘客id
     * @param tag 用户来源
     * @param orderNo 订单号
     * @param startAddress 出发地
     * @param startLng 出发地经度
     * @param startLat 出发地纬度
     * @param invitePhone 乘车人手机号
     * @param inviteName 乘车人姓名
     * @param endAddress 目的地
     * @param endLng 目的地经度
     * @param endLat 目的地纬度
     */
    private Integer updateApprovalOfficialOrder(
            Long userId,
            String tag,
            String orderNo,
            String startAddress,
            String startLng,
            String startLat,
            String invitePhone,
            String inviteName,
            String endAddress,
            String endLng,
            String endLat){
        List<OaCOrderApprovalOfficial> oaCOrderApprovalOfficials = oaCOrderApprovalOfficialMapper.selectList(
                Wrappers.<OaCOrderApprovalOfficial>lambdaQuery()
                        .eq(OaCOrderApprovalOfficial::getTag, tag)
                        .eq(OaCOrderApprovalOfficial::getOrderNo, orderNo)
                        .eq(OaCOrderApprovalOfficial::getUserId, userId));
        if (oaCOrderApprovalOfficials.size() != 1) {
            log.info(String.format("用户来源 %s,订单号 %s,未查到正确数量的乘客订单", tag, orderNo));
            throw PangException.create(EErrorCode.unInviteCarpoolOrder);
        }
        OaCOrderApprovalOfficial approvalOfficial = oaCOrderApprovalOfficials.get(0);
        // 订单不为 3司机已接单4司机前往预约地点5司机到达6行程中13私用行程 才可修改出发地
        Integer orderStatus = approvalOfficial.getOrderStatus();
        if (this.ifUpdateDeparture(orderStatus)){
            approvalOfficial.setEndAddress(endAddress);
            approvalOfficial.setEndLng(endLng);
            approvalOfficial.setEndLat(endLat);
        }
        approvalOfficial.setPassengerName(inviteName);
        approvalOfficial.setPassengerPhone(invitePhone);
        approvalOfficial.setStartAddress(startAddress);
        approvalOfficial.setStartLng(startLng);
        approvalOfficial.setStartLat(startLat);
        int i = oaCOrderApprovalOfficialMapper.updateById(approvalOfficial);
        if (i != 1){
            throw PangException.create(EErrorCode.updateInviteCarpoolOrderFailure);
        }
        // 更新redis订单
        this.updateRedisOrderNo(orderNo, JSON.toJSONString(approvalOfficial));
        return approvalOfficial.getInvoiceStatus();
    }

    /**
     * 判断是否可修改起始地
     * 订单不为 3司机已接单4司机前往预约地点5司机到达6行程中13私用行程 才可修改出发地
     * @param orderStatus 订单状态
     * @return
     */
    private boolean ifUpdateDeparture(Integer orderStatus){
        return !(EOrderStatus.driverOrder.getType().equals(orderStatus) ||
                EOrderStatus.reservationLocation.getType().equals(orderStatus) ||
                EOrderStatus.driverArrived.getType().equals(orderStatus) ||
                EOrderStatus.duringTrip.getType().equals(orderStatus) ||
                EOrderStatus.privateItinerary.getType().equals(orderStatus));
    }

    /**
     * 更新redis中订单
     *
     * @param orderNo
     */
    private void updateRedisOrderNo(String orderNo, String orderJson) {
        String key = RedisPrefixConstant.ORDER_OA_D_ORDER + orderNo;
        if (redisCommon.hashKey(key)) {
            redisCommon.set(key, orderJson);
        }
    }
}
